<template>
    <div class="canvas-container">
        <div class="canvas-controls">
            <el-button @click="clearAllDrawings">
                <el-icon>
                    <Delete />
                </el-icon>
            </el-button>
            <el-button @click="undo">
                <el-icon>
                    <Back />
                </el-icon>
            </el-button>
            <el-button @click="redo">
                <el-icon>
                    <Right />
                </el-icon>
            </el-button>
        </div>
        <canvas ref="canvas" :width="props.canvasWidth" :height="props.canvasHeight"
            style="border: 1px solid black"></canvas>
    </div>
</template>

<script setup>
import { onMounted, ref, watch } from "vue";
import { Delete, Back, Right } from '@element-plus/icons-vue'
const props = defineProps({
    imageUrl: {
        type: String,
        required: false
    },
    brushWidth: {
        type: Number,
        default: 5
    },
    isDrawingMode: {
        type: Boolean,
        default: true
    },
    isEraserMode: {
        type: Boolean,
        default: false,
    }  ,
    canvasHeight:{  
        type: Number,
        required: true
    },
    canvasWidth:{  
        type: Number,
        required: true
    },
});

const canvas = ref(null);
const fabricCanvas = ref(null);
// 前进 (需要保存历史记录)
const historyStack = ref([]);
const currentStateIndex = ref(-1);
const loadImage = () => {
    if (!fabricCanvas.value || !props.imageUrl) return;
    // 设置 fabric.js 的全局跨域设置
    fabric.Image.prototype.crossOrigin = 'anonymous';
    // 创建新的 Image 对象
    const img = new Image();
    img.crossOrigin = 'anonymous';
    img.src = props.imageUrl;
    img.onload = () => {
        // 先清空画布
        fabricCanvas.value.clear();

        // 计算尺寸和缩放
        const scaleX = fabricCanvas.value.width / img.width;
        const scaleY = fabricCanvas.value.height / img.height;
        const scale = Math.min(scaleX, scaleY);

        // 更新画布尺寸
        props.canvasWidth = img.width * scale
        props.canvasHeight = img.height * scale


        const left = (props.canvasWidth - img.width * scale) / 2;
        const top = (props.canvasHeight - img.height * scale) / 2;

        // Add the main image
        const fabricImage = new fabric.Image(img);
        fabricCanvas.value.setBackgroundImage(fabricImage, fabricCanvas.value.renderAll.bind(fabricCanvas.value), {
            scaleX: scale,
            scaleY: scale,
            left: left,
            top: top,
            originX: 'left',
            originY: 'top',
        });
    };
};

onMounted(() => {
    fabricCanvas.value = new fabric.Canvas(canvas.value, {
        allowTouchScrolling: true,
        preserveObjectStacking: true,
    });
    fabricCanvas.value.setDimensions({
        width: props.canvasWidth,
        height: props.canvasHeight
    });
    fabricCanvas.value.isDrawingMode = props.isDrawingMode;
    fabricCanvas.value.freeDrawingBrush.color = 'white'
    fabricCanvas.value.freeDrawingBrush.width = props.brushWidth;

    // Set up composite operation for transparency
    fabricCanvas.value.contextTop.globalCompositeOperation = 'destination-out';
    fabricCanvas.value.on('path:created', () => {
        // 保存当前状态
        const currentState = JSON.stringify(fabricCanvas.value.toJSON());

        // 如果在历史中间位置进行了新的绘制，需要清除之后的历史
        if (currentStateIndex.value < historyStack.value.length - 1) {
            historyStack.value = historyStack.value.slice(0, currentStateIndex.value + 1);
        }

        // 添加新状态
        historyStack.value.push(currentState);
        currentStateIndex.value++;
    });

    loadImage();

});

watch(() => props.imageUrl, () => {
    console.log(props.imageUrl)
    loadImage();
});

watch(() => props.brushWidth, (newWidth) => {
    if (fabricCanvas.value) {
        fabricCanvas.value.freeDrawingBrush.width = newWidth;
    }
})
// Watch drawing mode changes
watch(() => props.isDrawingMode, (newMode) => {
    if (fabricCanvas.value) {
        fabricCanvas.value.isDrawingMode = newMode;
    }
});


// 撤销功能
const undo = () => {
    if (currentStateIndex.value > 0) {
        currentStateIndex.value--;
        const prevState = JSON.parse(historyStack.value[currentStateIndex.value]);
        fabricCanvas.value.loadFromJSON(prevState, () => {
            fabricCanvas.value.renderAll();
        });
    }
};

// 恢复功能
const redo = () => {
    if (currentStateIndex.value < historyStack.value.length - 1) {
        currentStateIndex.value++;
        const nextState = JSON.parse(historyStack.value[currentStateIndex.value]);
        fabricCanvas.value.loadFromJSON(nextState, () => {
            fabricCanvas.value.renderAll();
        });
    }
};

// 清除所有画笔内容
const clearAllDrawings = () => {
    if (!fabricCanvas.value) return;
    const objects = fabricCanvas.value.getObjects();
    objects.forEach(obj => {
        if (obj !== fabricCanvas.value.backgroundImage) {
            fabricCanvas.value.remove(obj);
        }
    });
    fabricCanvas.value.renderAll();

    // 保存清除后的状态
    const currentState = JSON.stringify(fabricCanvas.value.toJSON());
    historyStack.value.push(currentState);
    currentStateIndex.value = historyStack.value.length - 1;
};

const getCanvasData = () => {
    if (!fabricCanvas.value) return null;
    return new Promise((resolve) => {
        const dataURL = fabricCanvas.value.toDataURL({
            format: 'png',
            quality: 1
        });
        // Convert base64 to blob
        fetch(dataURL)
            .then(res => res.blob())
            .then(blob => {
                // Create File object
                const file = new File([blob], 'mask.png', { type: 'image/png' });
                resolve(file);
            });
    });
};

defineExpose({
    getCanvasData
});
</script>

<style>
.canvas-container {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

.canvas-controls {
    padding: 10px;
    display: flex;
    gap: 10px;
    justify-content: flex-end;
    background: #fff;
}

:deep(.el-button) {
    padding: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
}

:deep(.el-icon) {
    font-size: 18px;
}
</style>